<template>
  <div id="weather-card" class="weather-card card-item">
    <div class="time-container">
      <span class="time">{{ timeInfo.time }}</span>
      <span class="date">{{ timeInfo.date }}</span>
      <span class="lunar-date">{{ timeInfo.lunarDate }}</span>
    </div>

    <div class="weather-container" @click="viewFutureWeatherClick">
      <div class="temperature">
        <span class="value">{{ weatherInfo.temperature }}°</span>
        <weather-icon :weather="weatherInfo.weather"/>
      </div>

      <div class="location">
        <span>{{ locationInfo.province + ' ' + locationInfo.city }}</span>
        <span>{{ weatherInfo.weather }}</span>
      </div>

      <div class="others">
        <div class="item">
          <i class="fa-solid fa-droplet"></i>
          <span>{{ weatherInfo.humidity }}%</span>
        </div>
        <div class="item">
          <i class="fa-solid fa-wind"></i>
          <span>{{ weatherInfo.winddirection }}风 </span>
          <span>{{ weatherInfo.windpower }}级</span>
        </div>
      </div>
    </div>

    <el-dialog v-model="weatherInfo.furtherWeatherDialog"
               title="未来3日天气" width="90%" :show-close="false"
               center class="weather-dialog">
      <div v-for="(item, index) in weatherInfo.furtherWeather.slice(0, 3)"
           :key="index" class="further-weather">
        <span v-if="index === 0">今天</span>
        <span v-else-if="index === 1">明天</span>
        <span v-else>后天</span>

        <weather-icon :weather="item.dayweather"/>

        <span>{{ getDayWeather(item.dayweather, item.nightweather) }}</span>

        <span class="temperature">{{ item.daytemp }}° / {{ item.nighttemp }}°</span>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import WeatherIcon from '@/components/Common/WeatherIcon.vue'
import { onMounted, onUnmounted, reactive } from 'vue'
import axios from 'axios'
import { Solar } from 'lunar-javascript'
import { ElNotification } from 'element-plus'
import { useAppStore } from '@/store/app.ts'

// 参考：https://lbs.amap.com/api/webservice/summary
const gaodeKey = 'a9c0309e3c4a808140ef522e9360c3cb'

const appStore = useAppStore()

type PeriodType = 'morning' | 'afternoon' | 'evening'

interface IFurtherWeather {
  date: string;
  daypower: string;
  daytemp: string;
  daytemp_float: string;
  dayweather: string;
  daywind: string;
  nightpower: string;
  nighttemp: string;
  nighttemp_float: string;
  nightweather: string;
  nightwind: string;
  week: string;
}

const weatherInfo = reactive({
  weather: '',
  temperature: '',
  humidity: '',
  winddirection: '',
  windpower: '',
  furtherWeatherDialog: false,
  furtherWeather: [] as IFurtherWeather[]
})

const timeInfo = reactive({
  timer: 0,
  time: '',
  date: '',
  lunarDate: ''
})

const locationInfo = reactive({
  location: '',
  adcode: '',
  country: '',
  province: '',
  city: '',
  district: ''
})

onMounted(async () => {
  getTimeInfo()
  timeInfo.timer = setInterval(() => {
    getTimeInfo()
  }, 1000)

  setWeatherCardBackground()
  setWelcomeNotion()
  await getGeoLocationByIpApi()
  await getGeoCodeApi(gaodeKey, locationInfo.location)
  await getWeatherApi(gaodeKey, locationInfo.adcode)
})

onUnmounted(() => {
  clearInterval(timeInfo.timer)
})

const setWeatherCardBackground = () => {
  let background = ''
  switch (getDayPeriod()) {
    case 'morning':
      background = 'linear-gradient(to right, #ff9a9e, #fad0c4)'
      break
    case 'afternoon':
      background = 'linear-gradient(to right, #00c6ff, #0072ff)'
      break
    case 'evening':
      background = 'linear-gradient(to right, #2c3e50, #000000)'
      break
    default:
      break
  }

  const cardElement = document.getElementById('weather-card')
  if (cardElement) {
    cardElement.style.background = background
  }
}

const setWelcomeNotion = () => {
  let title = ''
  let message = ''
  switch (getDayPeriod()) {
    case 'morning':
      title = '早上好 🌅'
      message = '清晨的阳光带来美好一天！'
      break
    case 'afternoon':
      title = '下午好 🌞'
      message = '忙碌之余别忘放松心情！'
      break
    case 'evening':
      title = '晚上好 🌙'
      message = '夜色温柔，静享美好时光！'
      break
    default:
      break
  }

  if (!appStore.isLogin) {
    ElNotification({ title, message, type: 'success' })
  }
  appStore.isLogin = true
}

const getDayPeriod = (): PeriodType => {
  const now = new Date()
  const hour = now.getHours()

  if (hour < 12) {
    return 'morning'
  } else if (hour >= 12 && hour < 18) {
    return 'afternoon'
  } else {
    return 'evening'
  }
}

const getGeoLocation = () => {
  return new Promise((resolve, reject) => {
    if (!('geolocation' in navigator)) {
      reject(new Error('您的浏览器不支持Geolocation API'))
    }

    navigator.geolocation.getCurrentPosition(resolve, reject)
  })
}

const getGeoLocationApi = async () => {
  try {
    const position = await getGeoLocation()
    locationInfo.location = `${position.coords.longitude},${position.coords.latitude}`
  } catch (e) {
    locationInfo.location = '119.028958,31.652127'
  }
}

const getGeoLocationByIpApi = async () => {
  try {
    const response = await axios.get('https://api.ip.sb/geoip')
    locationInfo.location = `${response.data.longitude},${response.data.latitude}`
  } catch (e) {
    locationInfo.location = '119.028958,31.652127'
  }
}

const getGeoCodeApi = async (key: string, location: string) => {
  const response = await axios.get('https://restapi.amap.com/v3/geocode/regeo', {
    params: {
      location,
      key
    }
  })

  const { addressComponent } = response.data.regeocode
  locationInfo.country = addressComponent.country
  locationInfo.province = addressComponent.province
  locationInfo.city = addressComponent.city
  locationInfo.district = addressComponent.district
  locationInfo.adcode = addressComponent.adcode
}

const getWeatherApi = async (key: string, city: string) => {
  const response = await axios.get('https://restapi.amap.com/v3/weather/weatherInfo', {
    params: {
      city,
      key
    }
  })

  const { lives } = response.data
  weatherInfo.weather = lives[0].weather
  weatherInfo.temperature = lives[0].temperature
  weatherInfo.humidity = lives[0].humidity
  weatherInfo.winddirection = lives[0].winddirection
  weatherInfo.windpower = lives[0].windpower
}

const getFurtherWeatherApi = async (key: string, city: string) => {
  const response = await axios.get('https://restapi.amap.com/v3/weather/weatherInfo', {
    params: {
      city,
      key,
      extensions: 'all'
    }
  })

  weatherInfo.furtherWeather = response.data.forecasts[0].casts
}

const getDayWeather = (dayWeather: string, nightWeather: string): string => {
  if (dayWeather === nightWeather) {
    return dayWeather
  } else {
    return `${dayWeather}转${nightWeather}`
  }
}

const getTimeInfo = () => {
  timeInfo.date = getCurrentDate()
  timeInfo.lunarDate = getCurrentLunarDate()
  timeInfo.time = getCurrentTime()
}

const getCurrentDate = (): string => {
  const now = new Date()

  const month = String(now.getMonth() + 1).padStart(2, '0')
  const day = String(now.getDate()).padStart(2, '0')

  const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
  const weekday = weekdays[now.getDay()]

  const hour = now.getHours()
  const timePeriod = hour < 12 ? '上午' : hour < 18 ? '下午' : '晚上'

  return `${month}月${day}日 ${weekday} ${timePeriod}`
}

const getCurrentTime = (): string => {
  const now = new Date()

  const hour = String(now.getHours()).padStart(2, '0')
  const minute = String(now.getMinutes()).padStart(2, '0')
  const second = String(now.getSeconds()).padStart(2, '0')
  return `${hour}:${minute}:${second}`
}

const getCurrentLunarDate = (): string => {
  const solar = Solar.fromDate(new Date())

  const lunarYear = solar.getLunar().getYearInGanZhi()
  const lunarShengxiao = solar.getLunar().getYearShengXiao()
  const lunarMonth = solar.getLunar().getMonthInChinese()
  const lunarDay = solar.getLunar().getDayInChinese()

  return `${lunarYear}(${lunarShengxiao})年 ${lunarMonth}月${lunarDay}`
}

const viewFutureWeatherClick = async () => {
  await getFurtherWeatherApi(gaodeKey, locationInfo.adcode)
  weatherInfo.furtherWeatherDialog = true
}
</script>

<style lang="scss">
.weather-card {
  // height: 200px;
  border-radius: 10px;
  padding: 10px;

  display: grid;
  grid-template-columns: repeat(2, 1fr);

  color: #FFFFFF;

  .time-container {
    display: flex;
    flex-direction: column;
    gap: 5px;

    .time {
      font-size: 2rem;
    }
  }

  .weather-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;

    .temperature {
      font-size: 2rem;
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .location, .others {
      display: flex;
      gap: 10px;

      .item {
        display: flex;
        align-items: center;
        gap: 5px;
      }
    }
  }

  .weather-dialog {
    background: linear-gradient(135deg, #708090 0%, #4682B4 100%);

    .el-dialog__title {
      color: #FFFFFF;
    }

    .el-dialog__close {
      color: #FFFFFF;
    }

    .el-dialog__body {
      color: #FFFFFF;
      display: flex;
      flex-direction: column;
      gap: 15px;

      .further-weather {
        display: grid;
        grid-template-columns: 30px 25px 2fr 1fr;
        align-items: center;
        gap: 5px;

        .temperature {
          justify-self: flex-end;
        }
      }
    }
  }
}
</style>
